# src/frontend/live_renderer.py
"""
支持精灵表裁切的实时渲染器 - 增强版路径查找
"""
import os
import pygame
from typing import Dict, Any, Optional, Tuple


class SpriteSheet:
    """精灵表类 - 处理32*32精灵裁切"""

    def __init__(self, filepath: str, sprite_size: Tuple[int, int] = (32, 32)):
        self.filepath = filepath
        self.sprite_size = sprite_size
        self.sprites = []

        print(f"尝试加载精灵表: {filepath}")

        # 检查Pygame是否已经正确初始化
        if not pygame.get_init():
            print("Pygame未初始化，跳过精灵表加载")
            self.sheet = None
            return

        # 检查display是否设置
        try:
            pygame.display.get_surface()
        except pygame.error:
            print("Pygame display未设置，跳过精灵表加载")
            self.sheet = None
            return

        if os.path.exists(filepath):
            try:
                self.sheet = pygame.image.load(filepath).convert_alpha()
                print(f"成功加载图像文件: {filepath}")
                print(f"图像尺寸: {self.sheet.get_width()}x{self.sheet.get_height()}")
                self._extract_sprites()
                print(f"成功提取 {len(self.sprites)} 个精灵")
            except Exception as e:
                print(f"加载精灵表失败: {filepath}, 错误: {e}")
                self.sheet = None
        else:
            print(f"精灵表文件不存在: {filepath}")
            self.sheet = None
    
    def _extract_sprites(self):
        """从精灵表中提取单个精灵"""
        if not self.sheet:
            return
        
        sheet_width = self.sheet.get_width()
        sheet_height = self.sheet.get_height()
        sprite_width, sprite_height = self.sprite_size
        
        cols = sheet_width // sprite_width
        rows = sheet_height // sprite_height
        
        print(f"精灵表分割: {cols}列 x {rows}行")
        
        for row in range(rows):
            for col in range(cols):
                x = col * sprite_width
                y = row * sprite_height
                sprite_rect = pygame.Rect(x, y, sprite_width, sprite_height)
                try:
                    sprite = self.sheet.subsurface(sprite_rect).copy()
                    self.sprites.append(sprite)
                except Exception as e:
                    print(f"提取精灵失败 [{row},{col}]: {e}")
    
    def get_sprite(self, index: int = 0) -> Optional[pygame.Surface]:
        """获取指定索引的精灵"""
        if 0 <= index < len(self.sprites):
            return self.sprites[index]
        elif self.sprites:
            return self.sprites[0]  # 返回第一个精灵作为默认
        return None
    
    def get_sprite_count(self) -> int:
        """获取精灵数量"""
        return len(self.sprites)

class AnimatedSprite:
    """动画精灵类"""
    
    def __init__(self, sprite_sheet: SpriteSheet, animation_speed: float = 0.2):
        self.sprite_sheet = sprite_sheet
        self.animation_speed = animation_speed
        self.current_frame = 0
        self.animation_timer = 0.0
        self.is_moving = False
    
    def update(self, dt: float, is_moving: bool = False):
        """更新动画"""
        self.is_moving = is_moving
        
        if is_moving and self.sprite_sheet.get_sprite_count() > 1:
            self.animation_timer += dt
            if self.animation_timer >= self.animation_speed:
                self.current_frame = (self.current_frame + 1) % self.sprite_sheet.get_sprite_count()
                self.animation_timer = 0.0
        else:
            self.current_frame = 0  # 静止时显示第一帧
    
    def get_current_sprite(self) -> Optional[pygame.Surface]:
        """获取当前帧精灵"""
        return self.sprite_sheet.get_sprite(self.current_frame)

class LiveRenderer:
    """增强的实时渲染器 - 支持精灵表和动画"""
    
    def __init__(self, width: int, height: int):
        self.width = width
        self.height = height
        
        # 计算渲染参数
        self.map_size = 17  # 地图大小 17x17
        self.cell_size = min(width, height) // (self.map_size + 2)
        self.map_offset_x = (width - self.map_size * self.cell_size) // 2
        self.map_offset_y = (height - self.map_size * self.cell_size) // 2
        
        print(f"渲染器参数: 画面{width}x{height}, 单元格{self.cell_size}x{self.cell_size}")
        
        # 查找资源目录
        self.assets_dir = self._find_assets_directory()
        print(f"资源目录: {self.assets_dir}")
        
        # 精灵表和动画
        self.sprite_sheets = {}
        self.animated_sprites = {}
        self.load_sprite_sheets()
        
        # 静态精灵
        self.static_sprites = {}
        self.load_static_sprites()
        
        # 动画计时
        self.last_update_time = pygame.time.get_ticks()
        
        # 颜色定义
        self.colors = {
            'wall': (100, 100, 100),        # 深灰色墙壁
            'floor': (200, 180, 140),       # 浅棕色地板
            'player': (0, 100, 255),        # 蓝色玩家（备用）
            'enemy': (255, 0, 0),           # 红色敌人（备用）
            'treasure': (255, 255, 0),      # 黄色宝藏（备用）
            'trap': (150, 0, 150),          # 紫色陷阱（备用）
            'background': (50, 50, 50)      # 背景色
        }
        
        print(f"渲染器初始化完成")

    # src/frontend/live_renderer.py - 只需要修改这个方法
    def _find_assets_directory(self):
        """智能查找资源目录 - 适配src/assets结构"""
        current_file = os.path.abspath(__file__)
        current_dir = os.path.dirname(current_file)

        print(f"当前文件路径: {current_file}")
        print(f"当前目录: {current_dir}")

        # 针对src/assets结构的路径查找
        possible_paths = [
            # 从 src/frontend 到 src/assets/sprites
            os.path.join(os.path.dirname(current_dir), 'assets', 'sprites'),
            # 绝对路径方式
            os.path.join(current_dir, '..', 'assets', 'sprites'),
            # 从工作目录查找
            os.path.join(os.getcwd(), 'src', 'assets', 'sprites'),
            os.path.join(os.getcwd(), 'assets', 'sprites'),
            # 备用路径
            os.path.join(current_dir, 'assets', 'sprites'),
        ]

        print("搜索资源目录...")
        for i, path in enumerate(possible_paths):
            abs_path = os.path.abspath(path)
            print(f"  {i + 1}. {abs_path}")
            if os.path.exists(abs_path):
                # 检查是否包含预期的资源文件
                expected_files = ['hero.png', 'stone.png', 'skeleton.png', 'knight.png', 'treasure.png', 'trap.png']
                found_files = []
                for file in expected_files:
                    if os.path.exists(os.path.join(abs_path, file)):
                        found_files.append(file)

                print(f"     找到文件: {found_files}")

                if found_files:
                    print(f"     ✓ 选择此目录: {abs_path}")
                    return abs_path
                else:
                    print(f"     × 目录存在但无资源文件")
            else:
                print(f"     × 目录不存在")

        print("未找到合适的资源目录，返回默认路径")
        return possible_paths[0]
    
    def load_sprite_sheets(self):
        """加载精灵表（行走图等）"""
        # 行走图精灵表
        walking_sprites = {
            'hero': 'hero.png',
            'skeleton': 'skeleton.png',
            'knight': 'knight.png'
        }
        
        print("加载精灵表...")
        for sprite_name, filename in walking_sprites.items():
            filepath = os.path.join(self.assets_dir, filename)
            sprite_sheet = SpriteSheet(filepath)
            
            if sprite_sheet.get_sprite_count() > 0:
                self.sprite_sheets[sprite_name] = sprite_sheet
                # 创建动画精灵
                self.animated_sprites[sprite_name] = AnimatedSprite(sprite_sheet, animation_speed=0.3)
                print(f"成功加载动画精灵: {sprite_name}")
            else:
                print(f"精灵表加载失败或为空: {sprite_name}")
    
    def load_static_sprites(self):
        """加载静态精灵（地板、宝藏、陷阱）"""
        static_files = {
            'stone': 'stone.png',
            'treasure': 'treasure.png',
            'trap': 'trap.png'
        }
        
        print("加载静态精灵...")
        for sprite_name, filename in static_files.items():
            filepath = os.path.join(self.assets_dir, filename)
            if os.path.exists(filepath):
                try:
                    sprite = pygame.image.load(filepath).convert_alpha()
                    print(f"原始{sprite_name}尺寸: {sprite.get_width()}x{sprite.get_height()}")
                    
                    # 缩放到单元格大小
                    scaled_sprite = pygame.transform.scale(sprite, (self.cell_size, self.cell_size))
                    self.static_sprites[sprite_name] = scaled_sprite
                    print(f"成功加载静态精灵: {sprite_name} -> {self.cell_size}x{self.cell_size}")
                except Exception as e:
                    print(f"加载静态精灵失败: {filename}, 错误: {e}")
            else:
                print(f"静态精灵文件不存在: {filepath}")
    
    def update_animations(self):
        """更新所有动画"""
        current_time = pygame.time.get_ticks()
        dt = (current_time - self.last_update_time) / 1000.0  # 转换为秒
        self.last_update_time = current_time
        
        # 更新所有动画精灵
        for animated_sprite in self.animated_sprites.values():
            animated_sprite.update(dt, is_moving=True)  # 简化：假设总是在移动
    
    def render(self, surface: pygame.Surface, game_state: Dict[str, Any]):
        """渲染游戏状态"""
        if not game_state:
            surface.fill(self.colors['background'])
            return
        
        # 更新动画
        self.update_animations()
        
        # 清空背景
        surface.fill(self.colors['background'])
        
        # 渲染地图
        self._render_map(surface, game_state.get('map', []))
        
        # 渲染游戏元素（按层次渲染）
        self._render_traps(surface, game_state.get('traps', []))
        self._render_treasures(surface, game_state.get('treasures', []))
        self._render_enemies(surface, game_state.get('enemies', []))
        self._render_player(surface, game_state.get('player', {}))
        
        # 渲染边框
        self._render_border(surface)
        
        # 渲染调试信息（可选）
        if hasattr(self, '_debug_mode') and self._debug_mode:
            self._render_debug_info(surface, game_state)
    
    def _render_map(self, surface: pygame.Surface, map_data: list):
        """渲染地图"""
        if not map_data:
            return
        
        for y in range(len(map_data)):
            for x in range(len(map_data[y]) if y < len(map_data) else 0):
                cell_x = self.map_offset_x + x * self.cell_size
                cell_y = self.map_offset_y + y * self.cell_size
                cell_rect = pygame.Rect(cell_x, cell_y, self.cell_size, self.cell_size)
                
                if map_data[y][x] == 1:  # 墙壁
                    pygame.draw.rect(surface, self.colors['wall'], cell_rect)
                    pygame.draw.rect(surface, (80, 80, 80), cell_rect, 1)
                else:  # 地板
                    if self.static_sprites.get('stone'):
                        # 使用stone.png作为地板纹理
                        surface.blit(self.static_sprites['stone'], cell_rect)
                    else:
                        # 备用地板渲染
                        pygame.draw.rect(surface, self.colors['floor'], cell_rect)
                        pygame.draw.rect(surface, (180, 160, 120), cell_rect, 1)
    
    def _render_player(self, surface: pygame.Surface, player_data: dict):
        """渲染玩家"""
        if not player_data:
            return
        
        x, y = player_data.get('x', 0), player_data.get('y', 0)
        cell_x = self.map_offset_x + x * self.cell_size
        cell_y = self.map_offset_y + y * self.cell_size
        
        # 使用动画精灵
        hero_sprite = self.animated_sprites.get('hero')
        if hero_sprite:
            current_sprite = hero_sprite.get_current_sprite()
            if current_sprite:
                # 缩放精灵到单元格大小
                scaled_sprite = pygame.transform.scale(current_sprite, (self.cell_size, self.cell_size))
                surface.blit(scaled_sprite, (cell_x, cell_y))
                return  # 成功渲染精灵，直接返回
        
        # 备用渲染
        self._draw_fallback_player(surface, cell_x, cell_y)
        
        # 绘制生命值条
        hp = player_data.get('hp', 100)
        max_hp = player_data.get('max_hp', 100)
        if hp < max_hp:
            self._draw_health_bar(surface, cell_x, cell_y, hp, max_hp, (0, 255, 0))
    
    def _render_enemies(self, surface: pygame.Surface, enemies: list):
        """渲染敌人"""
        for enemy in enemies:
            if enemy.get('hp', 0) <= 0:
                continue
            
            x, y = enemy.get('x', 0), enemy.get('y', 0)
            enemy_type = enemy.get('type', 'skeleton')
            
            cell_x = self.map_offset_x + x * self.cell_size
            cell_y = self.map_offset_y + y * self.cell_size
            
            # 使用动画精灵
            enemy_sprite = self.animated_sprites.get(enemy_type)
            if enemy_sprite:
                current_sprite = enemy_sprite.get_current_sprite()
                if current_sprite:
                    scaled_sprite = pygame.transform.scale(current_sprite, (self.cell_size, self.cell_size))
                    surface.blit(scaled_sprite, (cell_x, cell_y))
                    
                    # 绘制生命值条
                    hp = enemy.get('hp', 0)
                    max_hp = enemy.get('max_hp', hp)
                    if hp < max_hp:
                        self._draw_health_bar(surface, cell_x, cell_y, hp, max_hp, (255, 0, 0))
                    continue
            
            # 备用渲染
            self._draw_fallback_enemy(surface, cell_x, cell_y)
    
    def _render_treasures(self, surface: pygame.Surface, treasures: list):
        """渲染宝藏"""
        for treasure in treasures:
            if treasure.get('collected', False):
                continue
            
            x, y = treasure.get('x', 0), treasure.get('y', 0)
            cell_x = self.map_offset_x + x * self.cell_size
            cell_y = self.map_offset_y + y * self.cell_size
            
            if self.static_sprites.get('treasure'):
                surface.blit(self.static_sprites['treasure'], (cell_x, cell_y))
            else:
                self._draw_fallback_treasure(surface, cell_x, cell_y)
    
    def _render_traps(self, surface: pygame.Surface, traps: list):
        """渲染陷阱"""
        for trap in traps:
            if trap.get('triggered', False):
                continue
            
            x, y = trap.get('x', 0), trap.get('y', 0)
            cell_x = self.map_offset_x + x * self.cell_size
            cell_y = self.map_offset_y + y * self.cell_size
            
            if self.static_sprites.get('trap'):
                surface.blit(self.static_sprites['trap'], (cell_x, cell_y))
            else:
                self._draw_fallback_trap(surface, cell_x, cell_y)
    
    def _draw_fallback_player(self, surface: pygame.Surface, x: int, y: int):
        """绘制备用玩家图形"""
        center_x = x + self.cell_size // 2
        center_y = y + self.cell_size // 2
        radius = self.cell_size // 3
        pygame.draw.circle(surface, self.colors['player'], (center_x, center_y), radius)
        pygame.draw.circle(surface, (255, 255, 255), (center_x, center_y), radius, 2)
    
    def _draw_fallback_enemy(self, surface: pygame.Surface, x: int, y: int):
        """绘制备用敌人图形"""
        center_x = x + self.cell_size // 2
        center_y = y + self.cell_size // 2
        radius = self.cell_size // 3
        pygame.draw.circle(surface, self.colors['enemy'], (center_x, center_y), radius)
        pygame.draw.circle(surface, (150, 0, 0), (center_x, center_y), radius, 2)
    
    def _draw_fallback_treasure(self, surface: pygame.Surface, x: int, y: int):
        """绘制备用宝藏图形"""
        center_x = x + self.cell_size // 2
        center_y = y + self.cell_size // 2
        size = self.cell_size // 3
        rect = pygame.Rect(center_x - size//2, center_y - size//2, size, size)
        pygame.draw.rect(surface, self.colors['treasure'], rect)
        pygame.draw.rect(surface, (200, 200, 0), rect, 2)
    
    def _draw_fallback_trap(self, surface: pygame.Surface, x: int, y: int):
        """绘制备用陷阱图形"""
        center_x = x + self.cell_size // 2
        center_y = y + self.cell_size // 2
        radius = self.cell_size // 4
        pygame.draw.circle(surface, self.colors['trap'], (center_x, center_y), radius)
        pygame.draw.circle(surface, (100, 0, 100), (center_x, center_y), radius, 2)
    
    def _draw_health_bar(self, surface: pygame.Surface, x: int, y: int, hp: int, max_hp: int, color: tuple):
        """绘制生命值条"""
        if max_hp <= 0:
            return
        
        bar_width = self.cell_size - 4
        bar_height = 6
        bar_x = x + 2
        bar_y = y - 8
        
        # 背景条
        pygame.draw.rect(surface, (100, 0, 0), (bar_x, bar_y, bar_width, bar_height))
        # 生命值条
        hp_width = int(bar_width * (hp / max_hp))
        if hp_width > 0:
            pygame.draw.rect(surface, color, (bar_x, bar_y, hp_width, bar_height))
    
    def _render_border(self, surface: pygame.Surface):
        """渲染地图边框"""
        border_rect = pygame.Rect(
            self.map_offset_x - 2, 
            self.map_offset_y - 2,
            self.map_size * self.cell_size + 4,
            self.map_size * self.cell_size + 4
        )
        pygame.draw.rect(surface, (255, 255, 255), border_rect, 2)
    
    def _render_debug_info(self, surface: pygame.Surface, game_state: Dict[str, Any]):
        """渲染调试信息"""
        if not hasattr(pygame, 'font') or not pygame.font.get_init():
            return
        
        try:
            font = pygame.font.Font(None, 24)
            debug_info = [
                f"精灵表: {len(self.sprite_sheets)}",
                f"静态精灵: {len(self.static_sprites)}",
                f"资源目录: {os.path.basename(self.assets_dir)}",
            ]
            
            y_offset = 10
            for info in debug_info:
                text = font.render(info, True, (255, 255, 0))
                surface.blit(text, (10, y_offset))
                y_offset += 25
        except:
            pass
    
    def enable_debug(self):
        """启用调试模式"""
        self._debug_mode = True
    
    def disable_debug(self):
        """禁用调试模式"""
        self._debug_mode = False
    
    def update_size(self, width: int, height: int):
        """更新渲染器尺寸"""
        self.width = width
        self.height = height
        self.cell_size = min(width, height) // (self.map_size + 2)
        self.map_offset_x = (width - self.map_size * self.cell_size) // 2
        self.map_offset_y = (height - self.map_size * self.cell_size) // 2
        
        # 重新缩放静态精灵
        self.load_static_sprites()
        
        print(f"渲染器尺寸已更新: {width}x{height}, 单元格: {self.cell_size}x{self.cell_size}")